package com.glsc.ngateway.platform.service.other;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrDeptDto;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrDeptSearchDto;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrEmpDto;
import com.glsc.ngateway.common.api.ldap.dto.LdapEhrEmpSearchDto;
import com.glsc.ngateway.common.api.ldap.feign.IFeignLdapService;
import com.glsc.ngateway.common.api.ldap.resp.LdapResponse;
import com.glsc.ngateway.common.api.platform.dto.other.FortressAccountImportDto;
import com.glsc.ngateway.common.api.platform.dto.user.PlatformUserDto;
import com.glsc.ngateway.common.base.enums.OaHrmresourceStatusEnum;
import com.glsc.ngateway.common.base.repo.mysql.gateway.other.SystemLicenseExpireRepository;
import com.glsc.ngateway.platform.domain.Vpn;
import com.glsc.ngateway.platform.repo.VpnRepository;
import com.glsc.ngateway.platform.service.MailService;
import com.glsc.ngateway.platform.service.system.SystemMainService;
import com.glsc.ngateway.platform.utils.AssertOverride;
import com.glsc.ngateway.platform.utils.report.ReportFileConfigEnum;
import com.glsc.ngateway.platform.utils.report.ReportFileUtil;
import com.glsc.ngateway.platform.utils.report.ReportUploadContext;
import lombok.SneakyThrows;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.io.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class VpnService {

    private static final Logger logger = LoggerFactory.getLogger(VpnService.class);

    @Resource
    private SystemLicenseExpireRepository systemLicenseExpireRepository;

    @Resource
    private MailService mailService;
    @Resource
    private IFeignLdapService iFeignLdapService;
    @Resource
    private SystemMainService systemMainService;
    @Resource
    private VpnRepository vpnRepository;

    @PersistenceContext
    @Qualifier("entityManagerMysql")
    private EntityManager entityManager;

    @SneakyThrows
    @Transactional
    public ReportUploadContext<Vpn, String> upload(MultipartFile file, PlatformUserDto user) throws IOException {
        file = convertCsvToXlsx(file,-1);
        ReportUploadContext<Vpn, String> vpnRead = ReportUploadContext.<Vpn, String>builder()
                .config(ReportFileConfigEnum.VPN_IMPORT)
                .file(file)
                .build();
        ReportFileUtil.readSingleExcel(vpnRead);
        AssertOverride.notEmpty(vpnRead.getReadRes(), "sheet0不可为空");

//        ReportUploadContext<FortressAccountImportDto, String> fortressAccountContext = ReportUploadContext.<FortressAccountImportDto, String>builder()
//                .config(ReportFileConfigEnum.FORTRESS_ACCOUNT)
//                .file(file)
//                .check(this::checkCpuStandard)
//                .build();
//        ReportFileUtil.readSingleExcel(fortressAccountContext);
//        AssertOverride.notEmpty(fortressAccountContext.getReadRes(), "sheet1不可为空");

        LdapResponse<List<LdapEhrEmpDto>> ehrList = iFeignLdapService.getUserList(new LdapEhrEmpSearchDto());
        Map<String,LdapEhrEmpDto> ehrMap = ehrList.getData().stream().collect(Collectors.toMap(LdapEhrEmpDto::getBadge, Function.identity(), (key1, key2) -> key2));
        LdapResponse<List<LdapEhrDeptDto>> deptList = iFeignLdapService.getDepartmentList(new LdapEhrDeptSearchDto());
        Map<String,LdapEhrDeptDto> deptMap = deptList.getData().stream().map(e->{
            e.setDtitle(e.getDtitle().trim());
            return e;
        }).collect(Collectors.toMap(LdapEhrDeptDto::getDtitle, Function.identity(), (key1, key2) -> key2));
//        Map<String,FortressAccountImportDto> accountInfo = fortressAccountContext.getReadRes().stream().collect(Collectors.toMap(FortressAccountImportDto::getAccount, Function.identity(), (key1, key2) -> key2));
//        Map<String,List<Vpn>> machineInfo = vpnRead.getReadRes().stream().collect(Collectors.groupingBy(Vpn::getAccount));
        Map<String,List<Vpn>> machineInfo = new HashMap<>();
        //改成按照账号导入，没有资产的为空
        List<Vpn> fortressList = vpnRead.getReadRes();
        List<Vpn> fortressListAdd = new ArrayList<>();
        fortressList = fortressList.stream().filter(e -> !StrUtil.equals(e.getPathName(),"/国联证券/glsc")).collect(Collectors.toList());
        fortressList.forEach(e -> {
            //ehr匹配上，且部门能找到的人
            if (ehrMap.keySet().contains(e.getAccount()) && !"admin".equals(e.getAccount()) && ehrMap.get(e.getAccount()).getDeptinfo() != null) {
                e.setNotOa(0);
                //对一个用户多个机器的数据进行处理
                fillMultipleMachine(e,machineInfo,ehrMap,fortressListAdd);
            } else {
                e.setDepartmentOne("无法匹配人员");
                //对一个用户多个机器的数据进行处理
//                fillMultipleMachine(e,machineInfo,ehrMap,fortressListAdd);
            }
        });
//        fortressList = fortressList.stream().filter(e->{
//            return e.getNotOa() != 1;
//        }).collect(Collectors.toList());
        fortressList.addAll(fortressListAdd);
//        //异步处理
//        deleteAndSave(fortressList);
        vpnRepository.trancateTable();
        vpnRepository.saveAllAndFlush(fortressList);
        logger.info("vpn处理条数为"+fortressList.size());
        return vpnRead;
    }

    private void fillMultipleMachine(Vpn e, Map<String, List<Vpn>> machineInfo, Map<String, LdapEhrEmpDto> ehrMap, List<Vpn> fortressListAdd) {
//        List<Vpn> machineImportDtoList = machineInfo.get(e.getAccount());
//        if (CollectionUtil.isNotEmpty(machineImportDtoList) && machineImportDtoList.size() > 0){
//            for (int i = 0; i < machineImportDtoList.size(); i++) {
//                e.setMachine(machineImportDtoList.get(i).getMachine());
//                Vpn addFortress = new Vpn();
//                fillFortressInfo(e,ehrMap,ipSystemCodeMap,systemNameMap);
//                BeanUtils.copyProperties(e, addFortress);
//                addFortress.setMachine(machineImportDtoList.get(i).getMachine());
//                fortressListAdd.add(addFortress);
//            }
//        } else {
            fillFortressInfo(e,ehrMap);
//        }
    }

    private void fillInfoByPosition(LdapEhrDeptDto dept, Vpn e, Map<String, String> systemNameMap, Map<String, String> ipSystemCodeMap, String applyName) {
        if (StringUtils.isEmpty(e.getDepartmentOne())){
            String deparmentOneName = dept.getDepgrade().equals("一级部门") ? dept.getDtitle() : dept.getAtitle();
            e.setDepartmentOne(deparmentOneName.replaceAll("/","-"));
            e.setDepartmentOneId(dept.getDepgrade().equals("一级部门") ? dept.getDepid() : dept.getAdminid());
            e.setDepartmentTwo(dept.getDtitle());
            e.setDepartmentTwoId(dept.getDepid());
            e.setCompany(dept.getComptitle());
        }
//        fillSystemInfo(e,systemNameMap,ipSystemCodeMap);
        if (StringUtils.isNotEmpty(applyName)){
            e.setRemark(applyName+"申请");
        }

    }

    private Vpn fillFortressInfo(Vpn e, Map<String, LdapEhrEmpDto> ehrMap) {
        //                e.setStatus(accountInfo.get(e.getAccount()).getStatus());
        if (StringUtils.isEmpty(e.getDepartmentOne())){
            String deparmentOneName = ehrMap.get(e.getAccount()).getDeptinfo().getDepgrade().equals("一级部门") ? ehrMap.get(e.getAccount()).getDeptinfo().getDtitle() : ehrMap.get(e.getAccount()).getDeptinfo().getAtitle();
            try{
                e.setDepartmentOne(deparmentOneName.replaceAll("/","-"));
                e.setDepartmentOneId(ehrMap.get(e.getAccount()).getDeptinfo().getDepgrade().equals("一级部门") ? ehrMap.get(e.getAccount()).getDeptinfo().getDepid() : ehrMap.get(e.getAccount()).getDeptinfo().getAdminid());
                e.setDepartmentTwo(ehrMap.get(e.getAccount()).getDeptinfo().getDtitle());
                e.setDepartmentTwoId(ehrMap.get(e.getAccount()).getDeptinfo().getDepid());
                e.setOaStatus(ehrMap.get(e.getAccount()).getStatus());
                e.setName(ehrMap.get(e.getAccount()).getName());
            } catch (Exception exception){
                logger.error("无法匹配部门信息"+e.getAccount()+"--");
                exception.printStackTrace();
                e.setDepartmentOne("无法匹配人员");
            }

            if (!OaHrmresourceStatusEnum.isAlive(ehrMap.get(e.getAccount()).getStatus())){
                e.setDepartmentOne("无法匹配人员");
            }
            e.setCompany(ehrMap.get(e.getAccount()).getDeptinfo().getComptitle());
        }
//                e.setName(ehrMap.get(e.getAccount()).getName());
//                e.setAccountValidityFrom(accountInfo.get(e.getAccount()).getAccountValidityFrom());
//                e.setAccountValidityEnd(accountInfo.get(e.getAccount()).getAccountValidityEnd());
        return e;
    }

//    private void fillSystemInfo(Vpn e, Map<String, String> systemNameMap, Map<String, String> ipSystemCodeMap) {
//        if (StringUtils.isNotBlank(e.getIp())){
//            String ip = e.getIp().trim();
//            e.setSystemCode(ipSystemCodeMap.get(ip));
//            if(StringUtils.isNotBlank(e.getSystemCode())){
//                e.setSystemName(systemNameMap.get(e.getSystemCode()));
//            }
//        }
//    }

//    @Async
//    private void deleteAndSave(List<Vpn> fortressList) {
//
//    }

    private void checkCpuStandard(FortressAccountImportDto fortressAccountImportDto) {
    }

    private void checkCpuStandard(Vpn Vpn) {
    }

    @SneakyThrows
    public byte[] export(Vpn param) {
        List<Vpn> datas = vpnRepository.findAllByStatusIsNull();
        for (Vpn e :datas) {
            try {
                entityManager.detach(e);
            } catch (Exception exception) {
                logger.error("entityManager清除缓存error：", exception);
            }
            if("信息技术总部".equals(e.getDepartmentOne())){
                String departmentOne = e.getDepartmentTwo().replaceAll("/","-");
                e.setDepartmentOne(departmentOne);
                e.setOaStatus("");
            } else if (!"无法匹配人员".equals(e.getDepartmentOne())){
                e.setDepartmentOne(e.getCompany()+"-"+e.getDepartmentOne());
                e.setOaStatus("");
            } else {
                //除无法匹配人员部门有这列，其他都不显示这个数据
                e.setOaStatus(OaHrmresourceStatusEnum.fromCode(e.getOaStatus()));
            }
        }

        Map<String, List<Vpn>> dataMap = datas.stream().filter(e->e != null && e.getDepartmentOne() != null).collect(Collectors.groupingBy(Vpn::getDepartmentOne));
        List<String> sheetNames = dataMap.keySet().stream().collect(Collectors.toList());
        Collections.sort(sheetNames, Collections.reverseOrder());
        List<List<Vpn>> dataList = new ArrayList<>();
        for (String name :sheetNames) {
            Collections.sort(dataMap.get(name), (s1, s2) -> s1.getAccount().compareTo(s2.getAccount()));
            dataList.add(dataMap.get(name));
        }
        return ReportFileUtil.exportMultiSheet(dataList,sheetNames,ReportFileConfigEnum.VPN_EXPORT);
    }

    public Object search(Object paramsObj) {
        JSONObject objParmams = JSONObject.parseObject(JSONObject.toJSONString(paramsObj)).entrySet().stream()
                .filter(entry -> !entry.getValue().toString().isEmpty())
                .collect(JSONObject::new, (obj, entry) -> obj.put(entry.getKey(), entry.getValue()), JSONObject::putAll);

        if (StrUtil.isEmpty(objParmams.getString("orderByDirection"))) {
            objParmams.put("orderByDirection", "ASC");
        }
        if (StrUtil.isEmpty(objParmams.getString("orderByField"))) {
            objParmams.put("orderByField", "id");
        }
//        if (StringUtils.isEmpty(objParmams.getString("status"))){
//            objParmams.put("notStatus","禁用");
//        }
        Sort sort = Sort.by(Sort.Direction.fromString(objParmams.getString("orderByDirection")), objParmams.getString("orderByField"));

        Pageable pageable = PageRequest.of(objParmams.getInteger("pageNo") - 1, objParmams.getInteger("pageSize"), sort);

        Vpn paramSearchDto = JSONObject.parseObject(JSONObject.toJSONString(objParmams), Vpn.class);
        Page<Vpn> result = vpnRepository.searchByParam(pageable, paramSearchDto);
//        result.getContent().forEach(e -> {
//            if (e.getCmdbCpuStandard() != null) {
//                e.setPartNum(e.getCmdbCpuStandard().getPartNum());
//            }
//        });
        return result;

    }

    @SneakyThrows
    public ReportUploadContext<Vpn, String> uploadResource(MultipartFile file, PlatformUserDto user) {
//        清空文件前多余的内容
        file = convertCsvToXlsx(file, 4);
        file = delRow(file);

        ReportUploadContext<Vpn, String> vpnRead = ReportUploadContext.<Vpn, String>builder()
                .config(ReportFileConfigEnum.VPN_IMPORT)
                .file(file)
                .build();
        ReportFileUtil.readSingleExcel(vpnRead);
        AssertOverride.notEmpty(vpnRead.getReadRes(), "sheet0不可为空");
//        //异步处理
//        deleteAndSave(fortressList);
        List<Vpn> vpnList = vpnRepository.findAll();
        //本次读取内容
        Map<String,List<Vpn>> VpnMap = vpnRead.getReadRes().stream().collect(Collectors.groupingBy(Vpn::getNameExcelAccount));
        vpnList.forEach(e ->{
            List<Vpn> vpnList1 = VpnMap.get(e.getAccount());
            if (CollectionUtil.isNotEmpty(vpnList1)){
                Vpn v = vpnList1.get(0);
                if (e.getRemark() == null){
                    e.setRemark(v.getRemark());
                }
                e.setResourceName(v.getResourceName());
            }
        });
        vpnRepository.saveAllAndFlush(vpnList);
        return vpnRead;
    }

    private MultipartFile delRow(MultipartFile file) throws IOException {
        // 读取Excel文件
        Workbook workbook = new XSSFWorkbook(file.getInputStream());
        Sheet sheet = workbook.getSheetAt(0);

        int targetRowIndex = -1;

        // 遍历行，找到包含“权限报告：基于用户”的行
        for (Row row : sheet) {
            for (Cell cell : row) {
                if (cell.getCellType()  == CellType.STRING && cell.getStringCellValue().equals("权限报告：基于用户")) {
                    targetRowIndex = row.getRowNum();
                    break;
                }
            }
            if (targetRowIndex != -1) break;
        }

        // 删除从第2行到第i+2行的所有单元格
        if (targetRowIndex != -1) {
            for (int i = targetRowIndex+2; i >= 0; i--) {
                sheet.shiftRows(i  + 1, sheet.getLastRowNum(),  -1);
            }
        }


        // 生成新的Excel文件
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        workbook.write(bos);
        // 关闭工作簿
        workbook.close();
        byte[] bytes = bos.toByteArray();
        InputStream inputStream = new ByteArrayInputStream(bytes);

        // 转换为MultipartFile
        MultipartFile newFile = new MockMultipartFile("newFile.xlsx",  "newFile.xlsx",  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",  inputStream);
        return newFile;

    }

//    private MultipartFile delRow(MultipartFile file) {
//        // 读取 Excel 文件
//        Workbook workbook = new XSSFWorkbook(file.getInputStream());
//        Sheet sheet = workbook.getSheetAt(0);
//
//        // 查找特定行
//        int targetRowIndex = -1;
//        for (int i = 0; i <= sheet.getLastRowNum();  i++) {
//            Row row = sheet.getRow(i);
//            if (row != null) {
//                Cell cell = row.getCell(0);
//                if (cell != null && cell.getStringCellValue().contains(" 权限报告：基于用户")) {
//                    targetRowIndex = i;
//                    break;
//                }
//            }
//        }
//
//        // 删除指定行
//        if (targetRowIndex != -1) {
//            for (int i = 0; i < 3; i++) {
//                if (targetRowIndex + i <= sheet.getLastRowNum())  {
//                    sheet.removeRow(sheet.getRow(targetRowIndex  + i));
//                }
//            }
//        }
//
//        // 生成新的 Excel 文件
//        ByteArrayOutputStream bos = new ByteArrayOutputStream();
//        workbook.write(bos);
//        byte[] bytes = bos.toByteArray();
//        bos.close();
//
//        // 转换为 MultipartFile
//        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
//        MultipartFile newFile = new CommonsMultipartFile(new ByteArrayResource(bytes), file.getName(),  file.getContentType(),  bis);
//    }

//    public static MultipartFile convertCsvToXls(MultipartFile file) throws IOException {
//        // 创建一个新的XSSFWorkbook对象
//        Workbook workbook = new XSSFWorkbook();
//        Sheet sheet = workbook.createSheet("Sheet1");
//
//        // 读取CSV文件内容
//        InputStream inputStream = file.getInputStream();
//        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
//
//        String line;
//        int rowNum = 0;
//
//        while ((line = reader.readLine())  != null) {
//            Row row = sheet.createRow(rowNum++);
//            String[] data = line.split(",");
//
//            for (int i = 0; i < data.length;  i++) {
//                Cell cell = row.createCell(i);
//                cell.setCellValue(data[i]);
//            }
//        }
//
//        // 将Workbook写入ByteArrayOutputStream
//        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//        workbook.write(outputStream);
//        workbook.close();
//
//        // 创建一个新的MultipartFile对象
//        return new MockMultipartFile(
//                file.getName(),
//                file.getOriginalFilename(),
//                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
//                outputStream.toByteArray()
//        );
//    }

    /**
     * 转换文件格式，对于字段自己带逗号的，通过limitCol做限制前几列分割，负数是不做限制
     * @param csvFile
     * @param limitCol
     * @return
     * @throws IOException
     */
    public MultipartFile convertCsvToXlsx(MultipartFile csvFile, int limitCol) throws IOException {
        // 创建一个新的 XSSFWorkbook
        Workbook workbook = new XSSFWorkbook();

        // 获取第一个工作表
        Sheet sheet = workbook.createSheet("Sheet1");

        // 读取 CSV 文件的内容
        String csvContent = new String(csvFile.getBytes(),"gbk");

        // 解析 CSV 内容并将其写入工作表
        String[] lines = csvContent.split("\n");
        for (int i = 0; i < lines.length; i++) {
            String[] cells = lines[i].split(",", limitCol);
            Row row = sheet.createRow(i);
            for (int j = 0; j < cells.length; j++) {
                Cell cell = row.createCell(j);
                cell.setCellValue(cells[j].replace("\t", "").replace("\r", "").replace("\"", ""));
            }
        }

        // 将工作簿转换为字节数组
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        workbook.write(outputStream);

        // 创建一个新的 MultipartFile，并设置其内容为转换后的 XLSX 文件
        MultipartFile xlsxFile = new MockMultipartFile("converted.xlsx", outputStream.toByteArray());

        return xlsxFile;
    }
}
